# -*- shell-script -*-

# 21sysfs_hotplug - Definitions and routines relating to sysfs and hotplug.

# This file is part of the Linux lsvpd package.

# (C) Copyright IBM Corp. 2004, 2005

# Maintained by Martin Schwenke <martins@au.ibm.com>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    
# $Id: 21sysfs_hotplug,v 1.1 2006/04/11 18:38:28 emunson Exp $

[ -n "$sysfs_dir" ] || return 0

######################################################################

node_add_extra_hook_device ()
{
    local node_type="$1"
    local bus_info="$2"
    local subtype="$3"

    local source_node
    get_source_node "device" "$node_type" "$bus_info" "$subtype"
    [ -n "$source_node" ] || return 1  ### !!!

    local node
    retrieve_node "$bus_info"
    [ -n "$node" ] || return 1  ### !!!

    bus_alias_set "${source_node#/}" "$node"

    return 0
}    

######################################################################

hotplug_add_device ()
{
#set -x
#exec 2>/tmp/lsvpd.hotplug.log

    # Uses: DEVPATH (set by hotplug)

    bus_type="$1"

    local dl="${sysfs_dir}${DEVPATH}/device"
    
    wait_for_node "$dl"
    
    if [ -L "$dl" ] && cd -P "$dl" ; then
	local bus_addr="${PWD##*/}"  # basename
	cd "$OLDPWD"
	node_add "device" "$bus_type" "$bus_addr"
    else
	echo "$0: ${dl} did not appear" >&2
    fi
}

hotplug_remove_device ()
{
#set -x
#exec 2>/tmp/lsvpd.hotplug.log

    # Uses: DEVPATH (set by hotplug)

    bus_type="$1"

    local sysfs_bus_info="${sysfs_dir#/}${DEVPATH}"

    local node
    retrieve_node "$sysfs_bus_info"

    bus_alias_clear "$sysfs_bus_info"

    if [ -n "$node" ] ; then
	local bus_info t f
	f="${node}/lsvpd,bus-info"
	[ -f "$f" ] && read bus_info <"$f"
	[ -n "$bus_info" ] && bus_alias_clear "$bus_info"

	# Remove device OS dirs - contains overkill to avoid serious errors.
	local f="${node}/lsvpd,names"
	local names=""
	[ -r "$f" ] && read names <"$f"
	local n
	for n in $names ; do
	    local t="${db_os_dir}/device/${bus_type}/${n}"

	    if [ "$t" = "${t#${db_os_dir}}" ] ; then
		: "hotplug_remove_device: bad OS node \"${t}\"" 
	    else
		rm -rf "$t"
	    fi
	done
    
	# Remove $node - contains overkill to avoid serious errors.
	t="$node"
	if [ "$t" = "${t#${db_bus_dir}}" ] ; then
	    debug "hotplug_remove_device: bad bus directory \"${t}\"" 
	else
	    rm -rf "$t"
	fi
    fi
}

hotplug_name_and_crosslink ()
{
#set -x
#exec 2>/tmp/lsvpd.crosslink.log
    # Uses: DEVPATH

    bus_type="$1"

    local dl="${sysfs_dir}${DEVPATH}/device"
    
    wait_for_node "$dl"
	
    if [ -L "$dl" ] && cd -P "$dl" ; then
	local bus_addr="${PWD##*/}" # basename
	cd "$OLDPWD"

	node_add_name "device" "$bus_type" "$bus_addr"
    else
	echo "$0: ${dl} did not appear" >&2
    fi
}

######################################################################

wait_for_node ()
{
    local node="$1"
    local timeout="${2:-10}" # optional, default = 10 seconds

    local n=0
    while [ $n -lt $timeout -a ! -e "$node" ] ; do
	sleep 1
	n=$(($n + 1))
    done
}
